<?php
if (!class_exists('authcode'))
	require_once str_replace('\\', '/', __DIR__) . '/authcode.class.php';

// 图形验证码类
class verify {
	const option = array('width' => 110, // 图片宽度
		'height' => 40, // 图片高度
		'length' => 4, // 验证码字符数
		'ext' => 'gif', // 图片格式
		'type' => 2, //0 数字，1 英文字母，2 数字 + 英文字母，3 数学计算
		'fontSize' => 16, // 验证码字体大小
		'bg' => array(243, 251, 254), //背景颜色
		'expiry' => 300, //有效期（秒）
		'useCurve' => true, //干扰线
		'useNoise' => true //干扰色块
	);
	const dictionary = array('1234567890', 'ABCDEFGHJKLMNPQRTUVWXY', '3456789ABCDEFGHJKLMNPQRTUVWXY');
	
	protected static $_key = 'sdg.,7/sdg%5dg*ag"555/.5#%54'; // //COOKIE加密秘钥
	
	
	public static function entry($option = array()) { //生成验证码图片
		//  配置
		$option = array_merge(self::option, $option);
		if (isset($option['key']))
			self::$_key = $option['key'];
		
		$dictionary           = self::dictionary;
		$option['dictionary'] = $dictionary[$option['type'] < count($dictionary) ? $option['type'] : 0];
		
		$option['width'] || $option['width'] = $option['length'] * $option['fontSize'] * 1.5 + $option['fontSize'] * 1.5;
		
		$option['height'] || $option['height'] = $option['fontSize'] * 2;
		
		$_image = imagecreate($option['width'], $option['height']);
		
		imagecolorallocate($_image, $option['bg'][0], $option['bg'][1], $option['bg'][2]);
		
		$_color = imagecolorallocate($_image, mt_rand(1, 120), mt_rand(1, 120), mt_rand(1, 120));
		
		$ttf = str_replace('\\', '/', __DIR__) . '/ttfs/t1.ttf';
		
		if ($option['useNoise'])
			self::_writeNoise($_image, $option); //干扰色块
		
		if ($option['useCurve'])
			self::_writeCurve($_image, $_color, $option); //干扰线
		
		$code   = array();
		$codeNX = 0;
		
		for ($i = 0; $i < $option['length']; $i++) {
			$code[$i] = $option['dictionary'][mt_rand(0, strlen($option['dictionary']) - 1)];
			$codeNX += mt_rand($option['fontSize'] * 1.2, $option['fontSize'] * 1.6);
			
			imagettftext($_image, $option['fontSize'], mt_rand(-40, 70), $codeNX, $option['fontSize'] * 1.5, $_color, $ttf, $code[$i]);
		}
		
		setcookie('authcode', authcode::encode(strtolower(join('', $code)), self::$_key, $option['expiry']), time() + $option['expiry'], dirname($_SERVER['SCRIPT_NAME']), $_SERVER['HTTP_HOST']);
		
		header('Pragma: no-cache');
		if ($option['ext'] == "png") {
			@header("Content-Type:image/png");
		} elseif ($option['ext'] == "jpg") {
			@header("Content-Type:image/jpeg");
		} else {
			@header("Content-Type:image/gif");
		}
		
		imageJPEG($_image);
		imagedestroy($_image);
	}
	
	public static function check($captcha) { //验证验证码
		if (!isset($_COOKIE['authcode']) || trim($_COOKIE['authcode']) == '' || !($de = authcode::decode($_COOKIE['authcode'], self::$_key)))
			return '图形验证码已过期！';

		if (strtolower($captcha) !== $de)
			return '图形验证码错误！';
		
		return true;
	}
	
	protected static function _writeCurve($_image, $_color, $option) { //干扰线
		$A = mt_rand(1, $option['height'] / 2);
		$b = mt_rand($option['height'] / 4, $option['height'] / 4);
		$f = mt_rand($option['height'] / 4, $option['height'] / 4);
		$T = mt_rand($option['height'] * 1.5, $option['width'] * 2);
		$w = (2 * M_PI) / $T;
		
		$px1 = 0;
		$px2 = mt_rand($option['width'] / 2, $option['width'] * 0.667);
		for ($px = $px1; $px <= $px2; $px = $px + 0.9) {
			if ($w != 0) {
				$py = $A * sin($w * $px + $f) + $b + $option['height'] / 2;
				$i  = (int) (($option['fontSize'] - 6) / 4);
				while ($i > 0) {
					imagesetpixel($_image, $px + $i, $py + $i, $_color);
					$i--;
				}
			}
		}
		
		$A   = mt_rand(1, $option['height'] / 2);
		$f   = mt_rand($option['height'] / 4, $option['height'] / 4);
		$T   = mt_rand($option['height'] * 1.5, $option['width'] * 2);
		$w   = (2 * M_PI) / $T;
		$b   = $py - $A * sin($w * $px + $f) - $option['height'] / 2;
		$px1 = $px2;
		$px2 = $option['width'];
		for ($px = $px1; $px <= $px2; $px = $px + 0.9) {
			if ($w != 0) {
				$py = $A * sin($w * $px + $f) + $b + $option['height'] / 2;
				$i  = (int) (($option['fontSize'] - 8) / 4);
				while ($i > 0) {
					imagesetpixel($_image, $px + $i, $py + $i, $_color);
					$i--;
				}
			}
		}
	}
	
	protected static function _writeNoise($_image, $option) { //干扰色块
		for ($i = 0; $i < 10; $i++) {
			$noiseColor = imagecolorallocate($_image, mt_rand(150, 225), mt_rand(150, 225), mt_rand(150, 225));
			for ($j = 0; $j < 5; $j++) {
				imagestring($_image, 5, mt_rand(-10, $option['width']), mt_rand(-10, $option['height']), $option['dictionary'][mt_rand(0, strlen($option['dictionary']) - 1)], $noiseColor);
			}
		}
	}
}